/*
 * Copyright 2008. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the Apache License, Version 2.0. You
 * can find a copy of the license at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */

package com.sinai.mshab.visibility.rule;

import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

import com.sinai.mshab.visibility.VisibilityRule;
import com.sinai.mshab.widgets.AbstractRadioButtonGroup;
import com.sinai.mshab.widgets.HorizontalRadioButtonGroup;
import com.sinai.mshab.widgets.VerticalRadioButtonGroup;

/**
 * Exercise the {@link ShowIfGroupChecked} class.
 * 
 * @author Arthur Kalmenson
 */
public class ShowIfGroupCheckedTst extends GWTTestCase {

	VisibilityRule<AbstractRadioButtonGroup, Widget, String> rule;

	/**
	 * Test to insure that constructing a {@link ShowIfGroupChecked} with null
	 * arguments throws an {@link IllegalArgumentException}.
	 */
	public void testNullConstArgs() {

		// test various permutations.
		nullConstArgument(null, null, null);
		nullConstArgument(new HorizontalRadioButtonGroup("test",
				new String[] { "blah" }), null, null);
		nullConstArgument(null, "blah", null);
		nullConstArgument(null, null, new TextBox());
		nullConstArgument(new HorizontalRadioButtonGroup("test",
				new String[] { "blah" }), null, new PasswordTextBox());
	}

	/**
	 * Insure that an {@link IllegalArgumentException} is thrown with the given
	 * null arguments.
	 * 
	 * @param parent
	 *            the parent widget.
	 * @param value
	 *            the value of the trigger for the parent widget.
	 * @param child
	 *            the child widget.
	 */
	private void nullConstArgument(AbstractRadioButtonGroup parent,
			String value, Widget child) {

		try {
			rule = new ShowIfGroupChecked(parent, value, child);
			fail("Should have failed");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that when the {@link ShowIfGroupChecked} rule is created
	 * that the parent and child widgets remain visible.
	 */
	public void testVisibilityAtCreation() {

		rule = new ShowIfGroupChecked(new VerticalRadioButtonGroup("blah",
				new String[] { "test" }), "not testing", new CheckBox("Blah"));
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test to insure that when we put an empty radio collection, that the child
	 * widget appears.
	 */
	public void testEmptyRadio() {
		rule = new ShowIfGroupChecked(new VerticalRadioButtonGroup("blah",
				new String[] { "" }), "", new CheckBox("Blah"));

		// execute the rule and make sure the child is invisible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());
	}

	/**
	 * Test to insure that when the rule is set to a single value, and the
	 * parent widget is just created, that the child is invisible.
	 */
	public void testSingleRadioSingleTriggerChildNotVisible() {

		rule = new ShowIfGroupChecked(new VerticalRadioButtonGroup("blah",
				new String[] { "one" }), "hello", new CheckBox("Blah"));

		// execute the rule and make sure the child is invisible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());
	}

	/**
	 * Test to insure that when the rule has a single trigger, and we have a
	 * single RadioButton that is checked, that the child widget is show.
	 */
	public void testSingleRadioSingleTriggerChildVisible() {

		rule = new ShowIfGroupChecked(new VerticalRadioButtonGroup("blah",
				new String[] { "one" }), "one", new TextBox());

		// check the parent widget.
		rule.getParentWidget().setValue("one");

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test to insure that when a rule is has a single trigger, and we have
	 * multiple RadioButtons and the correct one is checked, that the child
	 * widget is show.
	 */
	public void testMultipleRadioSingleTriggerChildVisible() {

		rule = new ShowIfGroupChecked(new VerticalRadioButtonGroup("blah",
				new String[] { "one", "two", "three", "four" }), "two",
				new TextBox());

		// check the widget that's not to make it visible.
		rule.getParentWidget().setValue("one");

		// execute the rule and make sure the child is invisible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());

		// now check the correct widget.
		rule.getParentWidget().setValue("two");

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Check to make sure that even if we have multiple triggers and only one
	 * RadioButton, that the child is still visible when the appropriate trigger
	 * is set.
	 */
	public void testSingleRadioMultiTriggersChildVisible() {

		rule = new ShowIfGroupChecked(new VerticalRadioButtonGroup("blah",
				new String[] { "one" }), "hello", new TextBox());
		rule.addTrigger("test");
		rule.addTrigger("one");

		// make sure that adding multiple triggers doesn't make the parent and
		// child visible.
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());

		// check the parent widget.
		rule.getParentWidget().setValue("one");

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Check to make sure that when there are multiple triggers and multiple
	 * RadioButtons, and one or more of the triggers is selected, that the child
	 * widget appears.
	 */
	public void testMultiRadioMultiTriggersChildVisible() {

		rule = new ShowIfGroupChecked(new VerticalRadioButtonGroup("blah",
				new String[] { "one", "two", "three" }), "hello", new TextBox());
		rule.addTrigger("test");
		rule.addTrigger("one");
		rule.addTrigger("three");

		// check the parent widget.
		rule.getParentWidget().setValue("one");

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());

		// check the parent widget.
		rule.getParentWidget().setValue("two");

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());

		// check the parent widget.
		rule.getParentWidget().setValue("three");

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test setting the parent widget null. We expect an
	 * {@link IllegalArgumentException} to be thrown.
	 */
	public void testSetNullParent() {
		rule = new ShowIfGroupChecked(new HorizontalRadioButtonGroup("test",
				new String[] { "question1", "question2" }), "blah",
				new TextBox());
		try {
			rule.setParentWidget(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that setting a valid parent widget works.
	 */
	public void testValidParent() {
		rule = new ShowIfGroupChecked(new HorizontalRadioButtonGroup("test",
				new String[] { "question1" }), "blah", new TextBox());
		AbstractRadioButtonGroup parent = new VerticalRadioButtonGroup(
				"another test", new String[] { "one" });
		rule.setParentWidget(parent);
		assertEquals(parent, rule.getParentWidget());
	}

	/**
	 * Test to insure that setting a null child widget throws an
	 * {@link IllegalArgumentException}.
	 */
	public void testSetNullChild() {
		rule = new ShowIfGroupChecked(new HorizontalRadioButtonGroup("test",
				new String[] { "question1" }), "blah", new TextBox());
		try {
			rule.setChildWidget(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that setting a valid child widget works.
	 */
	public void testValidChild() {
		rule = new ShowIfGroupChecked(new HorizontalRadioButtonGroup("test",
				new String[] { "question1" }), "blah", new TextArea());
		CheckBox checkBox = new CheckBox("blah");
		rule.setChildWidget(checkBox);
		assertEquals(checkBox, rule.getChildWidget());
	}

	/**
	 * Test to insure adding a null trigger results in an
	 * {@link IllegalArgumentException} being thrown.
	 */
	public void testAddNullTrigger() {
		rule = new ShowIfGroupChecked(new HorizontalRadioButtonGroup("test",
				new String[] { "question1" }), "blah", new TextArea());
		try {
			rule.addTrigger(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	@Override
	public String getModuleName() {
		return "com.sinai.mshab.MshabVisibility";
	}
}
